package com.baselib.libnetwork.net.request;

import com.baselib.libnetwork.net.HttpManager;
import com.baselib.libnetwork.net.adapter.Call;
import com.baselib.libnetwork.net.base.Callback;
import com.baselib.libnetwork.net.base.ProgressRequestBody;
import com.baselib.libnetwork.net.model.HttpParams;
import com.baselib.libnetwork.net.adapter.OkHttpCall;
import com.baselib.libnetwork.net.base.Converter;
import com.baselib.libnetwork.net.model.HttpHeaders;

import java.io.IOException;
import java.io.Serializable;
import java.util.Map;

import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
 * @author lixuce
 * @version v1.0
 * @description
 * @since 2017/10/29
 */

public abstract class CustomRequest<T, R extends CustomRequest> implements Serializable {

    protected String url;
    public String BaseUrl;

    protected int retryCount;

    protected transient OkHttpClient client;
    protected transient Object tag;
    //默认缓存的超时时间
    protected HttpParams params = new HttpParams();     //添加的param
    protected HttpHeaders headers = new HttpHeaders();  //添加的header

    protected transient okhttp3.Request mRequest;
    protected Converter<T> converter;
    protected Callback<T> callback;

    protected transient Call<T> call;

    public CustomRequest(String url) {
        this.url = url;
        BaseUrl = url;
    }


    public R retryCount(int retryCount) {
        if (retryCount < 0) {
            throw new IllegalArgumentException("retryCount must > 0");
        }
        this.retryCount = retryCount;
        return (R) this;
    }

    public R client(OkHttpClient client) {
        this.client = client;
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R tag(Object tag) {
        this.tag = tag;
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R headers(HttpHeaders headers) {
        this.headers.put(headers);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R headers(String key, String value) {
        headers.put(key, value);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R removeHeader(String key) {
        headers.remove(key);
        return (R) this;
    }


    @SuppressWarnings("unchecked")
    public R params(HttpParams params) {
        this.params.put(params);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R params(Map<String, String> params, boolean... isReplace) {
        this.params.put(params, isReplace);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R params(String key, String value, boolean... isReplace) {
        params.put(key, value, isReplace);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R params(String key, int value, boolean... isReplace) {
        params.put(key, value, isReplace);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R params(String key, float value, boolean... isReplace) {
        params.put(key, value, isReplace);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R params(String key, double value, boolean... isReplace) {
        params.put(key, value, isReplace);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R params(String key, long value, boolean... isReplace) {
        params.put(key, value, isReplace);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R params(String key, char value, boolean... isReplace) {
        params.put(key, value, isReplace);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R params(String key, boolean value, boolean... isReplace) {
        params.put(key, value, isReplace);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R removeParam(String key) {
        params.remove(key);
        return (R) this;
    }

    @SuppressWarnings("unchecked")
    public R removeAllParams() {
        params.clear();
        return (R) this;
    }

    public HttpParams getParams() {
        return params;
    }

    public HttpHeaders getHeaders() {
        return headers;
    }

    public String getUrl() {
        return url;
    }

    public String getBaseUrl() {
        return BaseUrl;
    }

    public Object getTag() {
        return tag;
    }

    /**
     * 根据不同的请求方式和参数，生成不同的RequestBody
     */
    protected abstract RequestBody generateRequestBody();

    /**
     * 根据不同的请求方式，将RequestBody转换成Request对象
     */
    public abstract okhttp3.Request generateRequest(RequestBody requestBody);

    /**
     * 获取okhttp的同步call对象
     */

    public okhttp3.Call getRawCall() {
        //构建请求体，返回call对象
        final RequestBody requestBody = generateRequestBody();
        if (requestBody != null) {
            ProgressRequestBody<T> progressRequestBody = new ProgressRequestBody<>(requestBody, callback);
            mRequest = generateRequest(progressRequestBody);
        } else {
            mRequest = generateRequest(null);
        }

        if (client == null) {
            client = HttpManager.getInstance().okHttp();
        }
        return client.newCall(mRequest);
    }


    /**
     * 普通调用，阻塞方法，同步请求执行
     */
    public Response execute() throws IOException {
        return getRawCall().execute();
    }

    /**
     * 非阻塞方法，异步请求，但是回调在子线程中执行
     */
    public void execute(Callback<T> callback) {
        this.callback = callback;
        Call<T> call = adapt();
        call.execute(callback);
    }

    /**
     * Rx支持，获取同步call对象
     */
    public Call<T> adapt() {
        if (call == null) {
            return new OkHttpCall<>(this);
        } else {
            return call;
        }
    }

    public int getRetryCount() {
        return retryCount;
    }

    public Converter<T> getConverter() {
        // converter 优先级高于 callback
        if (converter == null) {
            converter = callback;
        }
        return converter;
    }

}
